#include "stdafx.h"
#include "ckSchemaReader.h"
#include "ckSchema.h"
#include "ckGroup.h"
#include "ckField.h"
#include "ckFieldDef.h"

#include "io.h"
#include "xDocument.h"
#include "xElement.h"
#include "xAttribute.h"

#include "ckValue.h"

namespace ck
{
	namespace data
	{
		SchemaReader::SchemaReader()
		{
		}


		SchemaReader::~SchemaReader()
		{
		}

		Schema*	SchemaReader::Read(const char* szPath)
		{
			if (!szPath)
			{
				return NULL;
			}
			if (_access(szPath,0)!=0)
			{
				return NULL;
			}

			z_int32 ret = 0;
			xml::Document xDoc;
			xDoc.SetKeepBlanks(false);
			ret = xDoc.Load(szPath);
			if (ret)
			{
				return NULL;
			}

			xml::Element* pxRoot = (xml::Element*)xDoc.GetRootNode();
			if (!pxRoot)
			{
				xDoc.Close();
				return NULL;
			}

			Schema* pSchema = new Schema();
			Group*  pGroup = NULL;

			xml::Element* pxGroup = NULL;
			pxRoot->Reset();
			while ((pxGroup = (xml::Element*)pxRoot->NextChild()))
			{
				pGroup = ParseGroup(pxGroup);
				if (pGroup)
				{
					pSchema->AddGroup(pGroup);
				}
			}

			return pSchema;
		}

		Group* SchemaReader::ParseGroup(xml::Element* pxGroup)
		{
			pxGroup->GetName();
			xml::Attribute* pxAttr = NULL;
			Group* pGroup = NULL;

			// Group Name
			pxAttr = pxGroup->GetAttribute("name");
			if (!pxAttr)
			{
				return NULL;
			}
			const char* groupName = pxAttr->GetValue();
			if ((groupName == NULL) || (strlen(groupName) == 0))
			{
				return NULL;
			}
			pGroup = new Group();
			pGroup->SetName(groupName);

			//Fields 
			xml::Element* pxField = NULL;
			FieldDef* pFieldDef = NULL;
			Field* pField = NULL;
			pxGroup->Reset();
			while ((pxField = (xml::Element*)pxGroup->NextChild()))
			{
				pField = ParseField(pxField);
				if (pField)
				{
					pGroup->AddField(pField);
				}
			}

			return pGroup;
		}

		Field* SchemaReader::ParseField(xml::Element* pxField)
		{
			xml::Attribute* pxAttr = NULL;
			FieldDef* pFieldDef = NULL;
			Field*	pField = NULL;

			// Field Name
			pxAttr = pxField->GetAttribute("name");
			if (!pxAttr)
			{
				return NULL;
			}
			const char* fieldName = pxAttr->GetValue();
			if ((fieldName == NULL) || (strlen(fieldName) == 0))
			{
				return NULL;
			}
			pField = new Field();			
			pField->SetName(fieldName);

			pFieldDef = new FieldDef();

			// Type
			pxAttr = pxField->GetAttribute("type");
			if (!pxAttr)
			{
				return NULL;
			}
			const char* type = pxAttr->GetValue();
			if ((type == NULL) || (strlen(type) == 0))
			{
				return NULL;
			}
			ckValueType mtype = Value::Parse(type);

			// Nullable
			bool nullable = true;
			pxAttr = pxField->GetAttribute("type");
			if (pxAttr)
			{
				const char* nb = pxAttr->GetValue();
				if ((nb != NULL) && (strlen(type) > 0))
				{
					nullable = (nb[0] == 'T');
				}
			}
			pFieldDef->Set((ckDataType)mtype, nullable);

			// precision
			z_int32 precision = 0;
			//if (mtype == ckValueTypeNumeric)
			if (mtype == ckValueTypeDouble|| mtype == ckValueTypeFloat)
			{
				pxAttr = pxField->GetAttribute("precision");
				if (pxAttr)
				{
					const char* pc = pxAttr->GetValue();
					if ((pc != NULL) && (strlen(pc) > 0))
					{
						precision = atoi(pc);
						pFieldDef->SetPrecision(precision);
					}
				}
			}

			// default value
//			Value* pValue = NULL;
//			pxAttr = pxField->GetAttribute("defaultvalue");
//			if (pxAttr)
//			{
//				const char* value = pxAttr->GetValue();
//				if ((value) && (strlen(value) > 0))
//				{
//					if ((value[0] == '{') && (value[strlen(value) - 1] == '}'))
//					{
//						char str[Z_PATH_MAX];
//						memset(str, 0, Z_PATH_MAX);
//						memcpy(str, value, strlen(value));
//						pValue = new Value(value);
//						//MetaFieldParameterValue* pParamValue = new MetaFieldParameterValue();
//						//pParamValue->SetText(value, strlen(value));
//						//pValue = pParamValue;
//					}
//					else
//					{
//						switch (mtype)
//						{
//						case ckValueTypeString:
//						{
//							char str[Z_PATH_MAX];
//							memset(str, 0, Z_PATH_MAX);
//							memcpy(str, value, strlen(value));
//							pValue = new Value(value);
//
//							//StringValue* pTxtValue = new StringValue();
//							//pTxtValue->SetText(value, strlen(value));
//							//pValue = pTxtValue;
//						}
//						break;
//						case ckValueTypeNumeric:
//						case ckValueTypeDouble:
//						{
//
//							
//							//NumericValue* pNumValue = new NumericValue();
//							//pNumValue->SetNumeric(atof(value));
//							//pNumValue->SetPrecision(precision);
//							//pValue = pNumValue;
//						}
//						break;
//						case ckValueTypeTime:
//						{
//
//						}
//						break;
////						case ckValueTypeTime:
//							break;
//						}
//					}
//
//					pFieldDef->SetDefaultValue(pValue);
//				}
//			}
			pField->SetFieldDef(pFieldDef);
			return pField;
		}
	}
}